﻿using EnvDTE;
using EnvDTE100;
using Sasa.QualityTools.CodeAnalysis.Common;
using System;
using System.Collections.Generic;
using System.IO;
using EnvDTE80;

namespace Sasa.QualityTools.CodeAnalysis.FxCopIntegrator
{
    internal static class PackageUtilities
    {
        //internal static string GetAssemblyPath(Project project)
        //{
        //    if (project == null)
        //    {
        //        throw new ArgumentNullException("project");
        //    }

        //    if (IsWebProject(project))
        //    {
        //        Logger.Info("Can't get assembly path because the specified project is a 'Web Site' project.");
        //        return null;
        //    }

        //    try
        //    {
        //        var directory = project.Properties.Item("FullPath").Value.ToString();
        //        var outputPath = project.ConfigurationManager.ActiveConfiguration.Properties.Item("OutputPath").Value.ToString();
        //        var outputFileName = project.Properties.Item("OutputFileName").Value.ToString();
        //        return Path.Combine(directory, outputPath, outputFileName);
        //    }
        //    catch (Exception e)
        //    {
        //        Logger.Error(String.Format("Failed to get assembly path of '{0}' project because: ", project.Name), e);
        //        return null;
        //    }
        //}

        internal static string GetFxCopProjectPath(Solution solution)
        {
            if (solution == null)
            {
                throw new ArgumentNullException("solution");
            }

            try
            {
                var directory = Path.GetDirectoryName(solution.FullName);
                return Path.Combine(directory, "CodeAnalysis", "CodeAnalysis.fxcop");
            }
            catch (Exception e)
            {
                Logger.Error(e, "Failed to get FxCop Project path because: ");
                return null;
            }
        }

        internal static IEnumerable<string> GetCodeAnalysisReportPaths(Solution solution, bool onlyShouldBuildProject = false)
        {
            if (solution == null)
            {
                throw new ArgumentNullException("solution");
            }

            foreach (var project in GetBuildTargetProjects(solution, onlyShouldBuildProject))
            {
                var path = GetCodeAnalysisReportPath(project);
                if (path != null)
                {
                    yield return path;
                }
            }
        }

        internal static string GetCodeAnalysisReportPath(Project project)
        {
            if (project == null)
            {
                throw new ArgumentNullException("project");
            }

            if (IsWebProject(project))
            {
                Logger.Info("Can't get code analysis report path because the specified project is a 'Web Site' project.");
                return null;
            }

            try
            {
                var directory = project.Properties.Item("FullPath").Value.ToString();
                var outputPath = project.ConfigurationManager.ActiveConfiguration.Properties.Item("OutputPath").Value.ToString();
                var reoprtFlieName = "CodeAnalysisReport.xml";
                return Path.Combine(directory, outputPath, reoprtFlieName);
            }
            catch (Exception e)
            {
                Logger.Error(e, String.Format("Failed to get code analysis report path of '{0}' project because: ", project.Name));
                return null;
            }
        }

        internal static IEnumerable<Project> GetBuildTargetProjects(Solution solution, bool onlyShouldBuildProject = false)
        {
            if (solution == null)
            {
                throw new ArgumentNullException("solution");
            }

            var projects = new List<Project>();

            try
            {
                foreach (BuildDependency dependency in solution.SolutionBuild.BuildDependencies)
                {
                    var contexts = solution.SolutionBuild.ActiveConfiguration.SolutionContexts;
                    for (int i = 1; i <= contexts.Count; i++)
                    {
                        if (dependency.Project.UniqueName == contexts.Item(i).ProjectName)
                        {
                            if (onlyShouldBuildProject)
                            {
                                if (contexts.Item(i).ShouldBuild)
                                {
                                    projects.Add(dependency.Project);
                                }
                            }
                            else
                            {
                                projects.Add(dependency.Project);
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                Logger.Error(e, "Failed to get build target projects because: ");
            }

            return projects;
        }

        internal static bool IsWebProject(Project project)
        {
            return (project != null) ? project.Kind == "{E24C65DC-7377-472b-9ABA-BC803B73C61A}" : false;
        }

        internal static string GetCodeAnalysisDirectory(Solution solution)
        {
            return Path.Combine(Path.GetDirectoryName(solution.FullName), "CodeAnalysis");
        }

        internal static string GetCodeAnalysisDirectory(Project project)
        {
            return Path.Combine(Path.GetDirectoryName(project.FullName), "CodeAnalysis");
        }

        internal static string[] GetCustomRuleSets(Solution solution)
        {
            var path = GetCodeAnalysisDirectory(solution);
            return (Directory.Exists(path)) ? Directory.GetFiles(path, "*.ruleset") : new string[0];
        }

        internal static string[] GetCustomRuleSets(Project project)
        {
            var path = GetCodeAnalysisDirectory(project);
            return (Directory.Exists(path)) ? Directory.GetFiles(path, "*.ruleset") : new string[0];
        }

        //internal static CodeAnalysisConfiguration LoadCodeAnalysisConfiguration(Solution solution)
        //{
        //    var path = Path.Combine(Path.GetDirectoryName(solution.FullName), "CodeAnalysis", "CodeAnalysisConfiguration.xml");
        //    if (File.Exists(path))
        //    {
        //        using (FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read))
        //        {
        //            //var serializer = new CodeAnalysisConfigurationSerializer();
        //            //return serializer.Deserialize(stream);
        //        }
        //    }

        //    return new CodeAnalysisConfiguration();
        //}

        //internal static void SaveCodeAnalysisConfiguration(Solution solution, CodeAnalysisConfiguration configuration)
        //{
        //    var dir = Path.Combine(Path.GetDirectoryName(solution.FullName), "CodeAnalysis");
        //    if (!Directory.Exists(dir))
        //    {
        //        Directory.CreateDirectory(dir);
        //    }

        //    var path = Path.Combine(dir, "CodeAnalysisConfiguration.xml");
        //    using (FileStream stream = new FileStream(path, FileMode.Create, FileAccess.Write))
        //    {
        //        //var serializer = new CodeAnalysisConfigurationSerializer();
        //        //serializer.Serialize(stream, configuration);
        //    }

        //    Project solutionFolder = GetCodeAnalysisSolutionFolder(solution);
        //    solutionFolder.ProjectItems.AddFromFile(path);
        //}

        //internal static CodeAnalysisConfiguration LoadCodeAnalysisConfiguration(Project project)
        //{
        //    var path = Path.Combine(Path.GetDirectoryName(project.FullName), "CodeAnalysis", "CodeAnalysisConfiguration.xml");
        //    if (File.Exists(path))
        //    {
        //        using (FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read))
        //        {
        //            //var serializer = new CodeAnalysisConfigurationSerializer();
        //            //return serializer.Deserialize(stream);
        //        }
        //    }

        //    return new CodeAnalysisConfiguration();
        //}

        //internal static void SaveCodeAnalysisConfiguration(Project project, CodeAnalysisConfiguration configuration)
        //{
        //    var dir = Path.Combine(Path.GetDirectoryName(project.FullName), "CodeAnalysis");
        //    ProjectItem folder = (Directory.Exists(dir)) ? project.ProjectItems.Item("CodeAnalysis") : project.ProjectItems.AddFolder("CodeAnalysis");

        //    var path = Path.Combine(dir, "CodeAnalysisConfiguration.xml");
        //    using (FileStream stream = new FileStream(path, FileMode.Create, FileAccess.Write))
        //    {
        //        //var serializer = new CodeAnalysisConfigurationSerializer();
        //        //serializer.Serialize(stream, configuration);
        //    }

        //    folder.ProjectItems.AddFromFile(path);
        //}

        //internal static CodeAnalysisConfiguration LoadCombinatedCodeAnalysisConfiguration(Project project)
        //{
        //    var forSolution = LoadCodeAnalysisConfiguration(project.DTE.Solution);
        //    Reconfigure(forSolution, project.DTE.Solution);
        //    var forProject = LoadCodeAnalysisConfiguration(project);
        //    Reconfigure(forProject, project);

        //    //var combinator = new CodeAnalysisConfigurationCombinator();
        //    //return combinator.Combine(forSolution, forProject);
        //}

        //private static void Reconfigure(CodeAnalysisConfiguration configuration, Solution solution)
        //{
        //    if (configuration.RuleSet.Value != null)
        //    {
        //        var tokens = configuration.RuleSet.Value.Split(new char[] { ';' }, 2);
        //        var dir = (tokens[0] == "Bundled") ? Path.Combine(Path.GetDirectoryName(typeof(PackageUtilities).Assembly.Location), "RuleSets") : PackageUtilities.GetCodeAnalysisDirectory(solution);
        //        configuration.RuleSet.Value = Path.Combine(dir, tokens[1]);
        //    }
        //}

        //private static void Reconfigure(CodeAnalysisConfiguration configuration, Project project)
        //{
        //    if (configuration.RuleSet.Value != null)
        //    {
        //        var tokens = configuration.RuleSet.Value.Split(new char[] { ';' }, 2);
        //        var dir = (tokens[0] == "Bundled") ? Path.Combine(Path.GetDirectoryName(typeof(PackageUtilities).Assembly.Location), "RuleSets") : PackageUtilities.GetCodeAnalysisDirectory(project);
        //        configuration.RuleSet.Value = Path.Combine(dir, tokens[1]);
        //    }
        //}

        private static Project GetCodeAnalysisSolutionFolder(Solution solution)
        {
            foreach (Project project in solution.Projects)
            {
                if (project.Name == "CodeAnalysis" && project.Kind == ProjectKinds.vsProjectKindSolutionFolder)
                {
                    return project;
                }
            }

            return ((Solution2)solution).AddSolutionFolder("CodeAnalysis");
        }
    }
}
